home *** CD-ROM | disk | FTP | other *** search
- // BEGIN FLOCK GPL
- //
- // Copyright Flock Inc. 2005-2007
- // http://flock.com
- //
- // This file may be used under the terms of of the
- // GNU General Public License Version 2 or later (the "GPL"),
- // http://www.gnu.org/licenses/gpl.html
- //
- // Software distributed under the License is distributed on an "AS IS" basis,
- // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- // for the specific language governing rights and limitations under the
- // License.
- //
- // END FLOCK GPL
-
- const Cc = Components.classes;
- const Ci = Components.interfaces;
-
- const FLOCK_PHOTO_API_MANAGER_CID = Components.ID('{18e27f2e-c99c-4915-9907-1a9fc0780ed6}');
-
- const nsISupports = Components.interfaces.nsISupports;
- const nsIClassInfo = Components.interfaces.nsIClassInfo;
- const nsIFactory = Components.interfaces.nsIFactory;
- const nsIProperties = Components.interfaces.nsIProperties;
- const nsILocalFile = Components.interfaces.nsILocalFile;
- const nsIFile = Components.interfaces.nsIFile;
- const nsIIOService = Components.interfaces.nsIIOService;
- const nsIFileProtocolHandler = Components.interfaces.nsIFileProtocolHandler;
- const nsIPreferenceService = Components.interfaces.nsIPrefBranch;
- const flockIPhotoAPIManager = Components.interfaces.flockIPhotoAPIManager;
- const flockIPhotoPeopleService = Components.interfaces.flockIPhotoPeopleService;
- const flockIPollingService = Components.interfaces.flockIPollingService;
- const flockIMigratable = Components.interfaces.flockIMigratable;
-
- const FLOCK_PHOTO_API_MANAGER_CONTRACTID = '@flock.com/photo-api-manager;1?';
- const FLOCK_PHOTO_CONTRACTID = '@flock.com/photo;1';
- const DIRECTORY_SERVICE_CONTRACTID = '@mozilla.org/file/directory_service;1';
- const LOCAL_FILE_CONTRACTID = '@mozilla.org/file/local;1';
- const PREFERENCES_CONTRACTID = '@mozilla.org/preferences-service;1';
- const IO_SERVICE_CONTRACTID = '@mozilla.org/network/io-service;1';
- const RDFCU_CONTRACTID = '@mozilla.org/rdf/container-utils;1';
- const MYWORLD_SERVICE_CONTRACTID = '@flock.com/myworld-service;1';
-
- const RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
- const FLOCK_NS = "http://flock.com/rdf#";
- const NC_NS = "http://home.netscape.com/NC-rdf#";
-
- /* for Cardinal migration */
- const OLD_PEOPLE_PHOTO_RDF_FILE = 'flock_people_photo.rdf';
- const OLD_PEOPLE_PHOTO_RDF_FILE_RELIC = 'flock_people_photo_old.rdf';
- const LIST_ACCOUNTS_ROOT = 'urn:flock:people:photo:lists:accounts';
- const MEDIA_FAVES_ROOT = 'urn:media:favorites';
-
- const RDFS = Components.classes['@mozilla.org/rdf/rdf-service;1']
- .getService (Components.interfaces.nsIRDFService);
- const IOS = Components.classes[IO_SERVICE_CONTRACTID]
- .getService(Components.interfaces.nsIIOService);
- const RDFCU = Components.classes[RDFCU_CONTRACTID]
- .getService(Components.interfaces.nsIRDFContainerUtils);
-
- function flockPhotoAPIManager() {
- this.processingQueue = {};
- this.mPrefService = Components.classes[PREFERENCES_CONTRACTID].getService(nsIPreferenceService);
-
- this.mLogger = Components.classes["@flock.com/logger;1"].createInstance(Components.interfaces.flockILogger);
- this.mLogger.init("photo");
- this.mLogger.info("starting up...");
-
- var inst = this;
- var timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
- var timerFunc = {
- notify: function(aTimer) {
- inst.updateStates();
- },
- }
- timer.initWithCallback(timerFunc, 5 * 1000, 1);
- }
-
- //flockIMigratable
-
- flockPhotoAPIManager.prototype.__defineGetter__("migrationName",
- function getter_migrationName() {
- return "Photo Accounts";
- });
-
- flockPhotoAPIManager.prototype.needsMigration =
- function needsMigration(oldVersion) {
- this.mLogger.info(".needsMigration('" + oldVersion + "')\n");
-
- if (oldVersion.substr(0, 3) == "0.7") { // migration from Cardinal (0.7.x)
- var oldPeoplePhotoFile = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties)
- .get("ProfD", Components.interfaces.nsIFile);
- oldPeoplePhotoFile.append(OLD_PEOPLE_PHOTO_RDF_FILE);
-
- if (oldPeoplePhotoFile.exists()) {
- this.mLogger.info("needs migration from 0.7.x\n");
- return true;
- }
- return false;
- } else if (oldVersion.substr(0, 3) == "0.9") { // migration from 0.9.X
- this.mLogger.info("needs migration from 0.9.X\n");
- return true;
- } else {
- return false;
- }
- }
-
- flockPhotoAPIManager.prototype.startMigration =
- function startMigration(oldVersion, aFlockMigrationProgressListener) {
- this.mLogger.info(".startMigration('" + oldVersion + "', 'aFlockMigrationProgressListener')\n");
- var ctxt = {
- oldVersion: oldVersion,
- listener: aFlockMigrationProgressListener
- };
-
- if (oldVersion.substr(0, 3) == "0.7") { // migration from Cardinal (0.7.x)
- var oldPeoplePhotoFile = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties)
- .get("ProfD", Components.interfaces.nsIFile);
- oldPeoplePhotoFile.append(OLD_PEOPLE_PHOTO_RDF_FILE);
-
- ctxt.oldPeoplePhotoFile = oldPeoplePhotoFile;
-
- if (oldPeoplePhotoFile.exists())
- ctxt.listener.onUpdate(0, "Migrating photo people");
-
- } else if (oldVersion.substr(0, 3) == "0.9") { // Migration from 0.9.x
- ctxt.listener.onUpdate(0, "Migrating account and media queries");
- }
-
- return { wrappedJSObject: ctxt };
- }
-
- flockPhotoAPIManager.prototype.finishMigration =
- function finishMigration(ctxtWrapper) {
- }
-
- flockPhotoAPIManager.prototype.doMigrationWork =
- function doMigrationWork(ctxtWrapper) {
- var ctxt = ctxtWrapper.wrappedJSObject;
- var oldVersion = ctxt.oldVersion;
-
- if (oldVersion.substr(0, 3) == "0.7") {
- if (!ctxt.oldPeoplePhotoFile.exists()) {
- return false;
- }
-
- if (!ctxt.photoMigrator) {
- ctxt.photoMigrator = this._migratePhotoPeople(ctxt);
- }
- if (ctxt.photoMigrator.next()) {
- ctxt.photoMigrator = null;
- }
-
- return Boolean(ctxt.photoMigrator);
- } else if (oldVersion.substr(0, 3) == "0.9") {
- this._migrate09xPhotoAccount();
- this._migrateMediaQueries(oldVersion);
- return false;
- }
- }
-
- // josh changed latestSeq property of mediaqueries from
- // an int to a string - we need to migrate this type change
- flockPhotoAPIManager.prototype._migrateMediaQueries =
- function _migrateMediaQueries(aOldVersion)
- {
- this.mLogger.info("._migrateMediaQueries()\n");
- var dataFileDS = RDFS.GetDataSource("rdf:flock-favorites");
-
- // get all media query rdf nodes
- var mqResource = RDFS.GetResource(FLOCK_NS+"CoopType");
- var mqLiteral = RDFS.GetResource(NC_NS+"MediaQuery");
- var mediaQueries = dataFileDS.GetSources(mqResource, mqLiteral, true);
-
- function getTargetInt(aSource, aArcName) {
- var target = dataFileDS.GetTarget(aSource, RDFS.GetResource(FLOCK_NS+aArcName), true);
- target instanceof Components.interfaces.nsIRDFInt;
- return target;
- };
- function getTargetLiteral(aSource, aArcName) {
- var target = dataFileDS.GetTarget(aSource,
- RDFS.GetResource(FLOCK_NS+aArcName),
- true);
- target instanceof Components.interfaces.nsIRDFLiteral;
- return target;
- };
- function getTargetDate(aSource, aArcName) {
- var target = dataFileDS.GetTarget(aSource,
- RDFS.GetResource(FLOCK_NS+aArcName),
- true);
- target instanceof Components.interfaces.nsIRDFDate;
- return target;
- };
-
- while (mediaQueries && mediaQueries.hasMoreElements()) {
- var mediaQuery = mediaQueries.getNext();
- mediaQuery.QueryInterface(Components.interfaces.nsIRDFResource);
- var subject = RDFS.GetResource(mediaQuery.Value);
- // For latestSeq, replace old int value with string if migrating
- // from 0.9.0.x
- if (aOldVersion.substr(0, 5) == "0.9.0") {
- var latestSeqInt = getTargetInt(mediaQuery, "latestSeq");
- var predicate = RDFS.GetResource(FLOCK_NS+"latestSeq");
- var latestSeqString = RDFS.GetLiteral(latestSeqInt.Value);
- dataFileDS.Change(subject, predicate, latestSeqInt, latestSeqString);
- }
-
- // Migrate the favicon url
- var iconPred = RDFS.GetResource(FLOCK_NS+"favicon");
- var faviconLit = getTargetLiteral(mediaQuery, "favicon");
- var svcShortNameLit = getTargetLiteral(mediaQuery, "svc");
- var icon = this.getAPIFromShortname(svcShortNameLit.Value).icon;
- var iconLit = RDFS.GetLiteral(icon);
- // Don't overwrite binary hardcoded favicons
- if (faviconLit.Value.match(/^chrome:/)) {
- dataFileDS.Change(subject, iconPred, faviconLit, iconLit);
- }
-
- var isPollable = getTargetLiteral(mediaQuery, "isPollable");
- if (isPollable.Value == "true") {
- // Force refresh on media query
- dataFileDS.Change(subject,
- RDFS.GetResource(FLOCK_NS + "nextRefresh"),
- getTargetDate(mediaQuery, "nextRefresh"),
- RDFS.GetDateLiteral((new Date()).getTime()*1000));
- }
- }
- }
-
- flockPhotoAPIManager.prototype._migrate09xPhotoAccount =
- function flockPhotoAPIManager__migrate09xPhotoAccount()
- {
- this.mLogger.info("._migrate09xPhotoAccount()");
-
- var acUtils = Cc["@flock.com/account-utils;1"]
- .getService(Ci.flockIAccountUtils);
- var _coopfile = "chrome://flock/content/common/load-faves-coop.js";
- var _coop = Cc["@flock.com/singleton;1"]
- .getService(Ci.flockISingleton)
- .getSingleton(_coopfile)
- .wrappedJSObject;
- var accounts = acUtils.getAccountsByInterface("flockIMediaWebService");
- while (accounts.hasMoreElements()) {
- var account = accounts.getNext();
- account = account.QueryInterface(Ci.flockIWebServiceAccount);
- this.mLogger.debug("_migrate09xPhotoAccount -- migrating " + account.urn);
- var c_acct = _coop.get(account.urn);
- var service = Cc[c_acct.serviceId].getService(Ci.flockIWebService);
- service.migrateAccount(c_acct.accountId, c_acct.name);
- }
- }
- flockPhotoAPIManager.prototype._migratePhotoPeople =
- function _migratePhotoPeople(ctxt)
- {
- // Load old datasource
- var oldPhotoPeepsDS = RDFS.GetDataSourceBlocking(IOS.newFileURI(ctxt.oldPeoplePhotoFile).spec);
- var acctsRoot = RDFS.GetResource(LIST_ACCOUNTS_ROOT);
- var streamsRoot = RDFS.GetResource("urn:flock:people:photo:lists:watched");
- var getValue = function (aSource, aArcName) {
- var target = oldPhotoPeepsDS.GetTarget(aSource, RDFS.GetResource(FLOCK_NS+aArcName), true);
- target instanceof Components.interfaces.nsIRDFLiteral;
- return target.Value;
- };
-
- // Migrate accounts
- var accounts = RDFCU.MakeSeq(oldPhotoPeepsDS, acctsRoot).GetElements();
- while (accounts && accounts.hasMoreElements()) {
- var account = accounts.getNext();
- account.QueryInterface(Components.interfaces.nsIRDFResource);
- var username = getValue(account, "username");
- var apiShortName = getValue(account, "apiShortName");
- var id = getValue(account, "id");
- var api = this.getAPIFromShortname(apiShortName);
- api.migrateAccount(id, username);
- }
-
- // Load new datasource
- var _coop = Components.classes["@flock.com/singleton;1"]
- .getService(Components.interfaces.flockISingleton)
- .getSingleton("chrome://flock/content/common/load-faves-coop.js")
- .wrappedJSObject;
- var mediaFavesURN = MEDIA_FAVES_ROOT;
- var mediaFaves = _coop.get(mediaFavesURN);
- if (!mediaFaves) {
- mediaFaves = new _coop.Folder(mediaFavesURN);
- _coop.favorites_root.children.add(mediaFaves);
- }
-
- // Migrate favorite photo streams
- var streams = RDFCU.MakeSeq(oldPhotoPeepsDS, streamsRoot).GetElements();
- while (streams && streams.hasMoreElements()) {
- var stream = streams.getNext();
- stream.QueryInterface(Components.interfaces.nsIRDFResource);
- var apiShortName = getValue(stream, "apiShortName");
- var id = getValue(stream, "id");
- var mediaqueryURN = MEDIA_FAVES_ROOT+apiShortName+":user:"+id+"|username:"+getValue(stream, "username");
- var mediaquery = new _coop.MediaQuery(
- mediaqueryURN,
- {
- serviceId: FLOCK_PHOTO_API_MANAGER_CONTRACTID,
- service: apiShortName,
- favicon: this.getAPIFromShortname(apiShortName).iconUrl,
- query: "user:"+id+"|username:"+getValue(stream, "username"),
- name: getValue(stream, "username"),
- isPollable: true
- }
- );
- mediaFaves.children.add(mediaquery);
- }
-
- // rename the old people photo file
- ctxt.oldPeoplePhotoFile.moveTo(null, OLD_PEOPLE_PHOTO_RDF_FILE_RELIC);
- yield true;
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Implementation
- //////////////////////////////////////////////////////////////////////////////
-
- //////////////////////////////////////////////////////////////////////////////
-
- flockPhotoAPIManager.prototype.mStates = {};
- flockPhotoAPIManager.prototype.mListeners = new Array();
-
- flockPhotoAPIManager.prototype.addListener = function(aListener) {
- if (aListener == null) {
- throw "Listener is null!!";
- }
- this.mListeners.push(aListener);
- }
-
- flockPhotoAPIManager.prototype.updateStates = function() {
- for(var p in this.mStates) {
- var shortName = p;
- var state = this.mStates[p];
- var api = this.getAPIFromShortname(p);
- var newState = api.authState;
- if(newState != state) {
- this.notify(api);
- }
- this.mStates[p] = newState;
- }
- }
-
- flockPhotoAPIManager.prototype.notify = function(aService) {
- for(var i=0;i<this.mListeners.length;++i) {
- this.mListeners[i].onAPIStateChange(aService);
- }
- }
-
- flockPhotoAPIManager.prototype.doLogin = function(aAccountURN) {
- // TODO: MAYBE FIXME (CDC):
- // I changed the param for this function from aShortname to aAccountURN
- // ... but I don't think this is actually called from anywhere so for now
- // I'm gonna just throw NOT_IMPLEMENTED instead of fixing it to handle the
- // new parameter. If it breaks things, I owe the first person who notices
- // it a bubble tea.
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
-
- var inst = this;
- var myListener = {
- onAuth: function() {
- inst.notify(service);
- inst.setDefaultService(service.shortName);
- },
- onError: function(aError) {
- for (var i=0; i < inst.mListeners.length; i++) {
- aError.QueryInterface(Components.interfaces.flockIError);
- try {
- var theError = {};
- theError.errorCode = aError.errorCode;
- theError.serviceErrorCode = aError.serviceErrorCode;
- theError.serviceErrorString = aError.serviceErrorString;
- theError.errorString = aError.errorString;
- inst.mListeners[i].onError(theError);
- } catch (ex) {
- this.mLogger.error(ex);
- }
- }
-
- },
- }
- var service = this.getAPIFromShortname(aShortname);
- service.login(null, myListener);
- this.notify(service);
- }
-
- flockPhotoAPIManager.prototype.doLogout = function(aShortname) {
- var service = this.getAPIFromShortname(aShortname);
- service.logout();
-
- // TODO - maybe change the default service to something that is enabled ???
-
- this.notify(service);
- }
-
-
- flockPhotoAPIManager.prototype.removeListener = function(aListener) {
- for(var i=0;i<this.mListeners.length;++i) {
- if(aListener==this.mListeners[i]) {
- this.mListeners.splice(i,1);
- break;
- }
- }
- }
-
-
- flockPhotoAPIManager.prototype.getAPIFromShortname = function(aShortname) {
- // JMC - Special case, me!
- if (aShortname == "preview") {
- return this;
- }
-
- var catman = Cc["@mozilla.org/categorymanager;1"]
- .getService(Ci.nsICategoryManager);
- var webServices = [];
- var e = catman.enumerateCategory("flockMediaProvider");
- while (e.hasMoreElements()) {
- var entry = e.getNext().QueryInterface(Ci.nsISupportsCString);
- if (!entry) {
- continue;
- }
- var contractID = catman.getCategoryEntry("flockMediaProvider", entry.data);
- var svc = Cc[contractID].getService(Ci.flockIWebService);
- if (svc.shortName == aShortname) {
- return svc;
- }
- }
- return null;
- }
-
-
- function loadLibraryFromSpec(aSpec)
- {
- var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
- .getService(Components.interfaces.mozIJSSubScriptLoader);
- loader.loadSubScript(aSpec);
- }
-
- loadLibraryFromSpec("chrome://flock/content/common/aggregate.js");
-
- flockPhotoAPIManager.prototype.supportsSearch = function (aQuery) {
- return false;
- }
-
- flockPhotoAPIManager.prototype.search = function (aListener, aQuery, aCount, aPage) {
- // JMC - PQ of all mediaquery objects with new stuff
- var faves_coop = Components.classes['@flock.com/singleton;1']
- .getService(Components.interfaces.flockISingleton)
- .getSingleton("chrome://flock/content/common/load-faves-coop.js")
- .wrappedJSObject;
-
- // JMC - If it's a page =1 request, perform the search
- // Otherwise, return the next batch from the cached results
- if (aPage > 1) {
- aListener.onSearchResult(this.myUnseenEnum);
- } else {
- var mediaQueries = faves_coop.MediaQuery.find({hasUnseenItems: true});
- var streams = [];
- for (x in mediaQueries) {
- var mediaquery = mediaQueries[x];
- streams.push(mediaquery.children.enumerate());
- }
- var aggUnSeen = filterStream( aggregatePhotoStreams( streams ), function(item) {
- return item && item.unseen;
- });
- var inst = this;
- this.myUnseenEnum = {
- hasMoreElements : function() {
- return this.mEnum.hasMoreElements();
- },
- getNext : function() {
- var child = this.mEnum.getNext();
- // JMC - Get the real flockIPhoto from the coop obj.
- var svcName = child.getParent().service;
- return inst.getAPIFromShortname(svcName).getPhotoFromRDFNode(child.id());
- },
- };
- this.myUnseenEnum.mEnum = aggUnSeen;
- aListener.onSearchResult(this.myUnseenEnum);
- }
- }
-
- flockPhotoAPIManager.prototype.__defineGetter__("services", function () {
- var ar = new Array();
- var catman = Cc["@mozilla.org/categorymanager;1"]
- .getService(Ci.nsICategoryManager);
- var webServices = [];
- var e = catman.enumerateCategory("flockMediaProvider");
- while (e.hasMoreElements()) {
- var entry = e.getNext().QueryInterface(Ci.nsISupportsCString);
- if (!entry) {
- continue;
- }
- var contractID = catman.getCategoryEntry("flockMediaProvider", entry.data);
- var svc = Cc[contractID]
- .getService(Ci.flockIWebService);
- if (svc instanceof Ci.flockIMediaWebService) {
- ar.push(svc);
- }
- }
-
- var rval = {
- getNext: function() {
- var rval = ar.shift();
- return rval;
- },
- hasMoreElements: function() {
- return (ar.length>0);
- },
- }
- return rval;
- })
-
- flockPhotoAPIManager.prototype.getPreferredServices = function() {
- try {
- var pref = this.mPrefService.getCharPref("flock.photo.preferredServices");
- var ar = pref.split(",");
- var rval = [];
- for(var i=0;i<ar.length;++i) {
- if(ar[i].length) rval.push(ar[i]);
- }
- return rval;
- } catch(e) {
- //debug(e);
- debug("getPreferredServices: No preferred services found, returning an empty set\n");
- return [];
- }
- }
-
- flockPhotoAPIManager.prototype.setPreferredServices = function(aArray) {
- var val = aArray.join(",");
- var pref = this.mPrefService.setCharPref("flock.photo.preferredServices", val);
- }
-
- flockPhotoAPIManager.prototype.getDefaultService = function() {
- try {
- var pref = this.mPrefService.getCharPref("flock.photo.lastService");
- if (pref && pref.length)
- return this.getAPIFromShortname(pref);
- } catch(e) {
- return null;
- }
- }
-
- flockPhotoAPIManager.prototype.setDefaultService = function(aShortname) {
- try {
- this.mPrefService.setCharPref("flock.photo.lastService", aShortname);
- } catch(e) {
- debug(e);
- }
- }
-
- flockPhotoAPIManager.prototype.__defineGetter__('preferredServices', function () {
- try {
- var inst = this;
- var ar = this.getPreferredServices();
- var rval = {
- getNext: function() {
- var shortName = ar.shift();
- var api = inst.getAPIFromShortname(shortName);
- return api;
- },
- hasMoreElements: function() {
- return (ar.length>0);
- },
- }
- return rval;
- } catch(e) {
- debug(e);
- }
- })
-
-
- flockPhotoAPIManager.prototype.__defineGetter__("hasNewMedia", function () {
- var faves_coop = Components.classes['@flock.com/singleton;1']
- .getService(Components.interfaces.flockISingleton)
- .getSingleton("chrome://flock/content/common/load-faves-coop.js")
- .wrappedJSObject;
- var mediaFavsFolder = faves_coop.get(MEDIA_FAVES_ROOT);
- return mediaFavsFolder.hasUnseenItems;
- })
-
- // This method has three responsibilities,
- // and two entry points.
- // First, it ensures that the mediaquery
- // contains the most recent 5 RichPhoto items.
- // Second, it ensures that RichPhoto items that are being
- // Freshly created are marked as "unseen".
- // Finally, it does NOT mark them as unseen on first refresh.
-
- // The enum is required to be sorted, newest first
-
- flockPhotoAPIManager.prototype.processPhotoStream =
- function photoAPI_processPhotoStream(aUrn, aEnum, bMarkUnseen)
- {
- var MAX_MEDIAQUERY_CHILDREN = 5;
- var faves_coop = Components.classes['@flock.com/singleton;1']
- .getService(Components.interfaces.flockISingleton)
- .getSingleton("chrome://flock/content/common/load-faves-coop.js")
- .wrappedJSObject;
-
- var myStream = faves_coop.get(aUrn);
- if (!myStream || this.processingQueue[aUrn]) {
- return;
- }
- this.processingQueue[aUrn] = true;
-
- // JMC - Pruning run, save to destroy children later
- var myStreamEnum = myStream.children.enumerateBackwards();
- var oldChildren = [];
- while (myStreamEnum.hasMoreElements())
- {
- var child = myStreamEnum.getNext();
- if (child) {
- oldChildren.push(child);
- myStream.children.remove(child);
- }
- }
-
- var biggestSeq = myStream.latestSeq;
- var latestDate = myStream.latestDate;
- var inst = this;
- var photoIndex = 1;
- var newContent = false;
- function myWorker(shouldYield) {
- while (aEnum.hasMoreElements() && photoIndex <= MAX_MEDIAQUERY_CHILDREN) {
- var photo = aEnum.getNext();
- photo.QueryInterface(Components.interfaces.flockIPhoto);
-
- // For streams with no uploadDate, we use now. Is that good?
- var photoDate = (photo.uploadDate) ? new Date(parseInt(photo.uploadDate)) : new Date();
- if (photoDate > latestDate) {
- latestDate = photoDate;
- biggestSeq = photo.id;
- }
-
- var urn = 'urn:flock:item:photo:'+myStream.service+':'+photo.id;
- var photoFav;
- photoFav = faves_coop.get(urn);
- var alreadyIn = (photoFav != null);
- if (!alreadyIn) {
- newContent = true;
- }
-
- // if it doesn't exist, create it
- if (!photoFav) {
- photoFav = new faves_coop.RichPhoto(urn, {
- datevalue: photoDate,
- URL: photo.webPageUrl,
- thumbnail: photo.thumbnail,
- cachedThumbnail: "",
- is_public: photo.is_public,
- is_video: photo.is_video,
- midSizePhoto: photo.midSizePhoto,
- name: photo.title,
- username: photo.username,
- userid: photo.userid,
- photoid: photo.id,
- largeSizePhoto: photo.largeSizePhoto
- });
- // add new photostream to myworld service queue
- var myworldService = Cc[MYWORLD_SERVICE_CONTRACTID].getService(Ci.flockIMyworldService);
- myworldService.queueResource(urn);
- }
-
- myStream.children.addOnce(photoFav);
-
- if (!myStream.firstRefresh && !alreadyIn && bMarkUnseen) {
- photoFav.unseen = true;
- }
- photoIndex++;
- if (shouldYield()) yield;
- }
-
- // if the old children aren't new children, and they're orphans, then destroy them
- for(var i =0; i < oldChildren.length; i++)
- {
- var child = oldChildren[i];
- if (child.getParents().length < 1)
- {
- child.destroy();
- }
- }
- // If we added a newer photo
- if (newContent) {
- myStream.latestSeq = biggestSeq;
- myStream.latestDate = latestDate;
- if (!myStream.firstRefresh && bMarkUnseen) {
- // JMC - Shouldn't this propagate?
- myStream.hasUnseenItems = true;
- var parent = myStream.getParent();
- if (parent)
- {
- parent.hasUnseenItems = true;
- }
- }
- }
- myStream.firstRefresh = false;
- if (myStream.latestDate != latestDate) {
- myStream.latestDate = latestDate;
- }
-
- inst.processingQueue[aUrn] = false;
- }
- schedule(0.3, 30, myWorker);
- }
-
- flockPhotoAPIManager.prototype.refresh = function(aUrn, aListener) {
-
- var faves_coop = Components.classes['@flock.com/singleton;1']
- .getService(Components.interfaces.flockISingleton)
- .getSingleton("chrome://flock/content/common/load-faves-coop.js")
- .wrappedJSObject;
- var photoAPIManager = this;
- var listener = function(aStream, aSearchListener) {
- this.mStream = aStream;
- this.mListener = aSearchListener;
- }
-
- var myStream = faves_coop.get(aUrn);
- if (!myStream) {
- aListener.onError();
- return;
- }
-
- listener.prototype.onSearchResult = function(aEnum) {
- photoAPIManager.processPhotoStream(aUrn, aEnum, true);
- this.mListener.onResult(null, null);
- };
-
- listener.prototype.onError = function(aError) {
- photoAPIManager.mLogger.error(aError);
- if(this.mListener) this.mListener.onError(aError);
- };
-
- var theApi = this.getAPIFromShortname(myStream.service);
- if (!theApi) {
- aListener.onResult(null, null);
- return;
- }
-
- theApi.search(new listener(myStream, aListener), myStream.query, 5, null);
- return;
-
- }
-
-
- flockPhotoAPIManager.prototype.flags = nsIClassInfo.SINGLETON;
- flockPhotoAPIManager.prototype.classDescription = "Flock Photo People Service";
- flockPhotoAPIManager.prototype.getInterfaces = function (count) {
- var interfaceList = [Components.interfaces.flockISocialWebService, flockIPhotoAPIManager, flockIPollingService,
- flockIMigratable, nsIClassInfo];
- count.value = interfaceList.length;
- return interfaceList;
- }
-
- flockPhotoAPIManager.prototype.getHelperForLanguage = function (count) {return null;}
-
- // JMC - Making this a social photo service for the preview stream
- flockPhotoAPIManager.prototype.QueryInterface =
- function (iid) {
- if (!iid.equals(Components.interfaces.flockISocialWebService) &&
- !iid.equals(flockIPhotoAPIManager) &&
- !iid.equals(flockIPollingService) &&
- !iid.equals(flockIMigratable) &&
- !iid.equals(nsIClassInfo) &&
- !iid.equals(nsISupports))
- throw Components.results.NS_ERROR_NO_INTERFACE;
- return this;
- }
-
- // Module implementation
- var PhotoPeopleModule = new Object();
-
- PhotoPeopleModule.registerSelf =
- function (compMgr, fileSpec, location, type)
- {
- compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
-
- compMgr.registerFactoryLocation(FLOCK_PHOTO_API_MANAGER_CID,
- "Flock Photo API Manager JS Component",
- FLOCK_PHOTO_API_MANAGER_CONTRACTID,
- fileSpec,
- location,
- type);
- var catman = Components.classes['@mozilla.org/categorymanager;1']
- .getService(Components.interfaces.nsICategoryManager);
-
- catman.addCategoryEntry('flockMigratable', 'photoservice', FLOCK_PHOTO_API_MANAGER_CONTRACTID, true, true);
- }
-
- PhotoPeopleModule.getClassObject =
- function (compMgr, cid, iid) {
- if (!cid.equals(FLOCK_PHOTO_API_MANAGER_CID))
- throw Components.results.NS_ERROR_NO_INTERFACE;
-
- if (!iid.equals(Components.interfaces.nsIFactory))
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
-
- return PhotoAPIManagerFactory;
- }
-
- PhotoPeopleModule.canUnload =
- function(compMgr)
- {
- return true;
- }
-
- /* factory object */
- var PhotoAPIManagerFactory = new Object();
-
- PhotoAPIManagerFactory.createInstance =
- function (outer, iid) {
- if (outer != null)
- throw Components.results.NS_ERROR_NO_AGGREGATION;
-
- return (new flockPhotoAPIManager()).QueryInterface(iid);
- }
-
- /* entrypoint */
- function NSGetModule(compMgr, fileSpec) {
- return PhotoPeopleModule;
- }
-
-
-
- // a utility for async scheduling:
-
- // cheap scheduler for javascript tasks
-
- // aSlice is the maximum timeslice in seconds. 0.5 or less is a good value
-
- // aPercent is the percent of wall-clock time that should be spent executing
- // the task - eg: 20 = one fifth of the time
-
- // aTask is defined to be a generator taking an function that evaluates
- // to true if it should yield like:
- // function task (should_yield) {
- // while (some_condition) {
- // do some work...
- // if (should_yield()) yield;
- // }
- // }
- // NOTE: should_yield() is fairly cheap but in a tight inner loop it might
- // make sense to call it every N cycles
-
- var timers = [];
- function schedule (aSlice, aPercent, aTask) {
- // convert percent to ratio
- var ratio = aPercent / 100.0;
-
- // convert slice to milliseconds
- var slice = aSlice * 1000.0;
-
- function milliseconds () { return (new Date ()).getTime (); }
- var wall_start = milliseconds ();
- var process_time = 0;
-
-
- var process_start = 0;
- function should_yield () {
- var now = milliseconds ();
- var so_far = now - process_start;
- var wall_time = now - wall_start;
- return so_far >= slice || ((wall_time * ratio) < (process_time + so_far));
- }
-
- var generator = aTask (should_yield);
-
- var timer = Components.classes['@mozilla.org/timer;1']
- .createInstance (Components.interfaces.nsITimer);
- var callback = {
- notify: function () {
- var wall_time = milliseconds () - wall_start;
-
- if ((wall_time * ratio) < process_time) {
- // if we've spent more time than we're supposed to
- // don't run this cycle
- }
-
- process_start = milliseconds ();
- try {
- generator.next ();
- } catch (err if err instanceof StopIteration) {
- // the task is complete
- timer.cancel ();
- for (var i=0; i<timers.length; i++) {
- if (timers[i] == timer) {
- timers.splice (i,1);
- }
- }
- timer = null;
- }
- process_time += (milliseconds () - process_start);
- }
- }
-
- timer.initWithCallback (callback, Math.round (slice/ratio),
- Components.interfaces.nsITimer.TYPE_REPEATING_SLACK)
- timers.push (timer);
- }
-